/*
 * Module:	Beep driver 
 * Author:	Lvjianfeng
 * Date:	2012.8
 */


#include "stm8l15x.h"

#include "drv.h"


//Constant definition

#define FREQUENCY_DEFAULT				4000


//Type definition

typedef enum
{
	DRV_BEEP_STATE_IDLE = 0,
	DRV_BEEP_STATE_ON,
	DRV_BEEP_STATE_OFF,
	DRV_BEEP_STATE_MUTE,
	DRV_BEEP_COUNT_STATE
} drv_beep_state;


//Private variable definition

static uint m_ui_State = {0};
static uint m_ui_BeepCount = {0};
static uint16 m_u16_Frequency = {0};
static uint16 m_u16_OnInterval = {0};
static uint16 m_u16_OffInterval = {0};
static uint16 m_u16_Timer = {0};


//Private function declaration


//Public function definition

uint DrvBEEP_Initialize(void)
{
	uint16 u16_Frequency;

	CLK->PCKENR3 |= CLK_PCKENR3_TIM5;

	u16_Frequency = FREQUENCY_DEFAULT;
	DrvBEEP_SetConfig(DRV_BEEP_PARAM_FREQUENCY, (const uint8 *)&u16_Frequency,
		sizeof(u16_Frequency));
	TIM5->PSCR = 0x00;
	TIM5->CCMR2 = 0x30;
	TIM5->CCER1 = 0x10;
	TIM5->CR1 = 0x00;
	TIM5->BKR |= TIM_BKR_AOE;

	return FUNCTION_OK;
}


uint DrvBEEP_SetConfig
(
	uint ui_Parameter,
	const uint8 *u8p_Value,
	uint ui_Length
)
{
	switch (ui_Parameter)
	{
		case DRV_BEEP_PARAM_FREQUENCY:
			m_u16_Frequency = *((const uint16 *)u8p_Value);
			TIM5->ARRH = (uint8)(((DRV_SYSTEM_CLOCK / 2) / m_u16_Frequency) >> 8);
			TIM5->ARRL = (uint8)((DRV_SYSTEM_CLOCK / 2) / m_u16_Frequency);
			TIM5->CCR2H = TIM5->ARRH;
			TIM5->CCR2L = TIM5->ARRL;
			break;
			
		case DRV_BEEP_PARAM_SWITCH:
			
			if (*((const uint *)u8p_Value) == 0)
			{
				if (m_ui_State != DRV_BEEP_STATE_MUTE)
				{
					DrvBEEP_Stop();
					m_ui_State = DRV_BEEP_STATE_MUTE;
				}
			}
			else
			{
				if (m_ui_State == DRV_BEEP_STATE_MUTE)
				{
					m_ui_State = DRV_BEEP_STATE_IDLE;
				}
			}

			break;

		default:
			return FUNCTION_FAIL;
	}

	return FUNCTION_OK;
}


uint DrvBEEP_GetConfig
(
	uint ui_Parameter,
	uint8 *u8p_Value,
	uint *uip_Length
)
{
	switch (ui_Parameter)
	{
		case DRV_BEEP_PARAM_FREQUENCY:
			*((uint16 *)u8p_Value) = m_u16_Frequency;
			break;
			
		case DRV_BEEP_PARAM_SWITCH:

			if (m_ui_State == DRV_BEEP_STATE_MUTE)
			{
				*((uint *)u8p_Value) = 0;
			}
			else
			{
				*((uint *)u8p_Value) = 1;
			}

			break;
			
		default:
			return FUNCTION_FAIL;
	}

	return FUNCTION_OK;
}


void DrvBEEP_Start
(
	uint ui_BeepCount,
	uint16 u16_OnInterval,
	uint16 u16_OffInterval
)
{
	if ((ui_BeepCount == 0) || (u16_OnInterval == 0) ||
		(m_ui_State == DRV_BEEP_STATE_MUTE))
	{
		return;
	}

	m_ui_BeepCount = ui_BeepCount;
	m_u16_OnInterval = u16_OnInterval;
	m_u16_OffInterval = u16_OffInterval;

	if (m_ui_State == DRV_BEEP_STATE_IDLE)
	{
		m_u16_Timer = 0;
		m_ui_State = DRV_BEEP_STATE_ON;
		TIM5->CR1 |= TIM_CR1_CEN;
	}
}


void DrvBEEP_Stop(void)
{
	if ((m_ui_State == DRV_BEEP_STATE_ON) ||
		(m_ui_State == DRV_BEEP_STATE_OFF))
	{
		m_ui_State = DRV_BEEP_STATE_IDLE;
		TIM5->CR1 &= ~TIM_CR1_CEN;
	}
}


void DrvBEEP_Tick
(
	uint16 u16_TickTime
)
{
	switch (m_ui_State)
	{
		case DRV_BEEP_STATE_ON:
			m_u16_Timer += u16_TickTime;

			if (m_u16_Timer >= m_u16_OnInterval)
			{
				m_u16_Timer = 0;

				if (m_u16_OffInterval == 0)
				{
					m_ui_State = DRV_BEEP_STATE_IDLE;
				}
				else
				{
					m_ui_State = DRV_BEEP_STATE_OFF;
				}

				TIM5->CR1 &= ~TIM_CR1_CEN;
			}

			break;

		case DRV_BEEP_STATE_OFF:
			m_u16_Timer += u16_TickTime;

			if (m_u16_Timer >= m_u16_OffInterval)
			{
				m_u16_Timer = 0;
				m_ui_BeepCount--;

				if (m_ui_BeepCount > 0)
				{
					m_ui_State = DRV_BEEP_STATE_ON;
					TIM5->CR1 |= TIM_CR1_CEN;
				}
				else
				{
					m_ui_State = DRV_BEEP_STATE_IDLE;
				}
			}

			break;

		default:
			break;
	}
}


#if DRV_BEEP_TEST_ENABLE == 1


void DrvBEEP_Test(void)
{

    TIM5->CR1 |= TIM_CR1_CEN;

/*	while (1)
	{
    	TIM5->CR1 |= TIM_CR1_CEN;
		for (i = 0; i < 60000; i++);
		TIM5->CR1 &= ~TIM_CR1_CEN;
		for (i = 0; i < 60000; i++);
	}*/
}

#endif


//Private function definition
